【React 教学】Step by Step 教你写一个日历控件 |
您所在的位置:网站首页 › react 教学 › 【React 教学】Step by Step 教你写一个日历控件 |
React 是一个用于构建用户界面的 javascript 库 (官网定义),很多人认为 React 是 MVC 中的 V(视图),React 采用下面几个主要的思想 简单 仅仅只要表达出你的应用程序在任一个时间点应该长的样子,然后当底层的数据变了,React 会自动处理所有用户界面的更新。 声明式 (Declarative) 数据变化后,React 概念上与点击“ 刷新” 按钮类似,但仅会更新变化的部分。 构建可组合的组件 React 都是关于构建可复用的组件。事实上,通过 React 你唯一要做的事情就是构建组件。得益于其良好的封装性,组件使代码复用、测试和关注分离(separation of concerns)更加简单。 疯狂 React 挑战了很多传统的知识,第一眼看上去可能很多想法有点疯狂。当你阅读完这篇教程,你会对 React 的产生更多的喜爱。 下面就直奔主题一步一步为大家讲解怎么用 React 构建一个简单的日历控件,最终结果如下图所示:
为了便于讲解,后续增加的 js 和 css 都写在这个 CalendarControl.html 文件里,点击这里查看 demo。 Step1:搭建页面 为了运行 React,首先你需要搭建一个页面,结构大致如下: CalendarControl.html: 1234567891011 1 2 3 4下面对标行逐一做个解释: line1 支持中文编码 line2 react.js 是运行 React 的框架,请自行去官网下载:https://facebook.github.io/react/downloads.html line3 browser.min.js 的作用是将 JSX 语法转为 JavaScript 语法 line4 script 标签的 type 属性为 text/babel 。这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加 上 type="text/babel" 其次,上面代码一共用了两个库: react.js 和 Browser.js ,它们必须首先加载。其中,Browser.js 的作用是将 JSX 语法转为 JavaScript。这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。 Step2: 将界面分解
将代码分解后,代码结构如下: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 var CalendarHeader = React.createClass({ render:function(){ return( 20月 2015年 ) } }); var CalendarBody = React.createClass({ render:function(){ return( SUN MON TUE WED THU FRI SAT 1 2 3 4 5 6 7 ) } }); var CalendarControl = React.createClass({ render:function(){ return( ) } }); React.render( , document.body );注: 1、React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类。上面代码中一共有 3 个组件:CalendarHeader 、CalendarBody 、CalendarControl 其中 CalendarHeader 、CalendarBody 是子组件,CalendarControl 是父组件。 2、组件的用法与原生的 HTML 标签完全一致,可以任意加入属性,比如 ,就是 CalendarBody 组件加入一个 year 属性,值为 2015。组件的属性可以在组件类的 this.props 对象上获取,比如 year 属性就可以通过 this.props.year 读取。 3、React.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。所有组件类都必须有自己的 render 方法,用于输出组件。 4、HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 语法,它允许 HTML 与 JavaScript 的混写, JSX 的基本语法规则:遇到 HTML 标签(以 更多事件可以参考:https://facebook.github.io/react/docs/events.html Step5 点击左右箭头,实现改变年月 如何实现月份年份的转变?首先获取当前年月,再根据左右箭头改变年月。 1234567891011121314151617181920212223242526272829303132333435363738394041 var CalendarHeader = React.createClass({ getInitialState:function(){ var newDate = new Date(); return { year:this.formatDate(newDate,'yyyy'), month:parseInt(this.formatDate(newDate,'MM')), }; }, handleLeftClick:function(){ var newMonth = parseInt(this.state.month) - 1; var year = this.state.year; if(newMonth 12 ){ year ++; newMonth = 1; } this.state.month = newMonth; this.state.year=year; this.setState(this.state); }, render:function(){ return( {this.state.month}月 {this.state.year}年 ) } });this.formatDate() 是一个封装的日期格式转换函数,这里就不作讲解了,可以去源代码里看。 这里要重点介绍 state 状态: 组件免不了要与用户互动,React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI。 上面上面代码是一个 CalendarHeader 组件,它的 getInitialState 方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。 Step6 改变月份,渲染日历表 我们知道要渲染一个日历表,需要算出 1、当年当月有多少天 2、每月的 1 号是星期几 在仔细看下这张图,如果改变月份,渲染日历表,那么就需要在 CalendarHeader 和 CalendarBody 之间进行通信。
现在的问题是:怎么进行子组件间的通信? 1、其实在 React 中只要父组件状态值(this.state)发生改变,子组件也会重新渲染,这样我们想到的是: 如果子组件 CalendarHeader 状态值改变后,同时也改变父组件 CalendarControlr 的状态,使父组件 CalendarControlr 状态值也发生改变,一旦父组件 CalendarControlr 状态发生改变后,那么 CalendarControlr 下的子组件 CalendarBody 也会重新渲染。 2、所以在父组件 CalendarControlr 传一个回调函数给子组件 CalendarHeader,这样当子组件 CalendarHeader 的值改变时,调用这个回调函数,改变父组件 CalendarHeader 的状态值,这样就可以渲染到 CalendarBody 子组件了,这是比较通常的实现两个子组件之间通信的做法:核心是把父组件作为中间组件来传递。如下面示意图:
具体步骤: 1、把初始状态从子组件 CalendarHeader 放到父组件 CalendarControl: 1234567 getInitialState:function(){ var newDate = new Date(); return { year:util.formatDate(newDate,'yyyy'), month:parseInt(util.formatDate(newDate,'MM')), }; }2、然后在父组件 CalendarControl 添加一个回调函数 123456 handleFilterUpdate: function(filterYear,filterMonth) { this.setState({ year: filterYear, month: filterMonth });}3、然后把回调传给子组件 CalendarHeader: 1234567891011121314 render:function(){ return( ) }4、然后在子组件 CalendarHeader 的 handleLeftClick 和 handleRightClick 事件中调用这个回调函数。 12345678910111213141516171819202122232425 handleLeftClick:function(){ var newMonth = parseInt(this.state.month) - 1; var year = this.state.year; if(newMonth 12 ){ year ++; newMonth = 1; } this.state.month = newMonth; this.state.year=year; this.setState(this.state); this.props.updateFilter(year,newMonth); }这样就实现子→ 父 → 子之间的通信,然后就可以很顺利的渲染日期了(见下一步)。 this.props 对象的属性与组件的属性一一对应,组件的属性可以在组件类的 this.props 对象上获取,比如 year 属性就可以通过 this.props.year 读取。由于 this.props 和 this.state 都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props 表示那些一旦定义,就不再改变的特性,而 this.state 是会随着用户互动而产生变化的特性。 Step7 最后加上渲染日期函数 算出当年当月有多少天,以及每月的 1 号是星期几,在 CalendarBody 里加上: 1234567891011121314151617 getMonthDays:function(){ //根据月份获取当前天数 var year = this.props.year, month = this.props.month; var temp = new Date(year,month,0); return temp.getDate(); }, getFirstDayWeek:function(){ //根据年月返回当月1号是星期几 var year = this.props.year, month = this.props.month; var dt = new Date(year+'/'+month+'/1');//new Date(year,month,1); var Weekdays = dt.getDay(); return Weekdays; }并在 CalendarControl 的 render 里渲染: 这里渲染要注意了,改变父组件的状态值,需要在其 render 里渲染才有效果,并且返回的的应该是 html 标签而不是字符串: 123456789101112131415161718192021222324252627282930313233 render:function(){ var arry1 =[],arry2 = []; var getDays = this.getMonthDays(), FirstDayWeek = this.getFirstDayWeek(), day = this.props.day ; for(var i = 0 ;i 1234567891011121314 var arry1 =[],arry2 = []; var getDays = this.getMonthDays(), FirstDayWeek = this.getFirstDayWeek(), day = this.props.day ; for(var i = 0 ;i |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |